class Relation < ActiveRecord::Base
  belongs_to    :character
  belongs_to    :title
  
  def Relation.categories
    {
    1 => "Liege",
    2 => "Ally",
    3 => "Claim",
    4 => "War",
    5 => "Truce"
    }
  end
  
  def Relation.declare_war(character, enemy)
    declare_peace character, enemy # clear any existing wars and truces between the parties
    Relation.create_relationship character, enemy, 4
    Relation.create_relationship enemy, character, 4
  end
  
  def Relation.declare_truce(character, enemy)
    declare_peace character, enemy # clear any existing wars and truces between the parties
    Relation.create_relationship character, enemy, 5
    Relation.create_relationship enemy, character, 5
  end
  
  def Relation.declare_peace(character, enemy)
    Relation.cancel_relationship character, enemy, 4
    Relation.cancel_relationship character, enemy, 5
    Relation.cancel_relationship enemy, character, 4
    Relation.cancel_relationship enemy, character, 5
  end
  
  def Relation.cancel_alliances(character)
    alliances = Relation.find_allies character
    if alliances
      alliances.each do |ally|
        Relation.cancel_alliance character, ally
      end
    end
  end
  
  def Relation.cancel_alliance(character, ally)
    Relation.cancel_relationship character, ally, 2
    Relation.cancel_relationship ally, character, 2
  end
  
  def Relation.allies? (character, ally)
    Relation.relationship? character, ally, 2
  end
  
  def Relation.war? (character, enemy)
    Relation.relationship? character, enemy, 4
  end
  
  def Relation.truce? (character, enemy)
    Relation.relationship? character, enemy, 5
  end
  
  def Relation.peace? (character, enemy)
    !(Relation.war?(character,enemy) || Relation.truce?(character,enemy))
  end
  
  def Relation.create_alliance(character, ally)
    Relation.create_relationship character, ally, 2
    Relation.create_relationship ally, character, 2
  end
  
  def Relation.free_vassals(liege)
    vassals = Relation.find_vassals liege
    if vassals
      vassals.each do |vassal|
        Relation.cancel_vassalage(vassal)
      end
    end
  end
  
  def Relation.transfer_vassals(from, to)
    vassals = Relation.find_vassals from
    if vassals
      vassals.each do |vassal|
        Relation.vassalize(vassal, to)
      end
    end
  end
  
  def Relation.transfer_alliances(from, to)
    Relation.transfer_relationships from, to, 2
  end
  
  def Relation.transfer_claims(from, to)
    Relation.transfer_relationships from, to, 3
  end
  
  def Relation.transfer_wars(from, to)
    Relation.transfer_relationships from, to, 4
  end
  
  def Relation.transfer_truces(from, to)
    Relation.transfer_relationships from, to, 5
  end
  
  def Relation.cancel_vassalage(vassal)
    raise "Invalid vassal" unless vassal
    prev_liege_rel = Relation.find_liege vassal
    if prev_liege_rel
      prev_liege = prev_liege_rel.title.character unless prev_liege_rel.nil? or prev_liege_rel.title.nil?
      Relation.cancel_relationship vassal, prev_liege, 1 unless prev_liege.nil?
      Title.revoke_court_titles vassal
    end
  end
  
  def Relation.vassalize (vassal, liege)
    raise "Invalid liege" unless liege
    Relation.cancel_vassalage vassal
    # set new relationship
    Relation.create_relationship vassal, liege, 1
  end
  
  def Relation.find_liege (character)
    rel = Relation.find_from character, 1
    return rel[0] unless rel.nil?
  end
  
  def Relation.find_vassals (character)
    Relation.find_to character, 1
  end
  
  def Relation.find_allies (character)
    Relation.find_from character, 2
  end

  def Relation.find_claims (character)
    Relation.find_from character, 3
  end

  def Relation.find_wars (character)
    Relation.find_from character, 4
  end

  def Relation.find_truces (character)
    Relation.find_from character, 5
  end
  
  def to_character
    return title.character unless title.nil?
  end
  
  def category_name
    Relation.categories[self.category]
  end
  
  protected
  def Relation.find_from (character, category, to = nil)
    return nil unless character && category
    return Relation.find_all_by_category_and_character_id(category, character.id) unless to
    sql = Relation.sql_select_from_relation + " WHERE r.character_id = #{character.id} "
    sql += " AND r.title_id IN (" + sql_clause_title(to) + ")"
    sql += Relation.sql_sort_by_prestige
    Relation.find_by_sql sql
  end
  
  def Relation.find_to (character, category, from = nil)
    return nil unless character && category
    sql = Relation.sql_select_from_relation + " WHERE r.title_id IN (" + sql_clause_title(character) + ")"
    sql += " AND r.character_id = #{from.id}" unless from.nil?
    sql += Relation.sql_sort_by_prestige
    Relation.find_by_sql sql
  end
  
  def Relation.transfer_relationships(from, to, category)
    raise "Invalid arguments" unless from && to && category
    relations = Relation.find_from from, category
    if relations
      relations.each do |rel|
        Relation.cancel_relationship from, rel, category
        Relation.cancel_relationship rel, from, category
        Relation.create_relationship to, rel, category
        Relation.create_relationship rel, to, category
      end
    end
  end
  
  def Relation.cancel_relationship(from, to, category)
    raise "Invalid arguments" unless from && to && category
    relations = Relation.find_from from, category, to
    if relations
      for relation in relations
        relation.destroy
      end
    end
  end
  
  def Relation.create_relationship(from, to, category)
    raise "Invalid arguments" unless from && to && category
    relation = Relation.find_from from, category, to
    if relation.nil? or relation.size < 1
      relation = Relation.new
      relation.character_id = from.id
      relation.title_id = to.highest_title.id
      relation.category = category
      relation.save
    end
    return relation
  end
  
  def Relation.relationship? (from, to, category)
    return false unless from && to && category
    return true unless Relation.find_from(from, to, category).nil?
    return false
  end
  
  def Relation.sql_select_from_relation
    "SELECT r.id, r.character_id, r.title_id, r.category, r.created_at, r.updated_at, c.prestige FROM relations r RIGHT JOIN characters c ON c.id = r.character_id "
  end
  
  def Relation.sql_clause_title (character)
    " SELECT id FROM titles WHERE character_id = #{character.id} "
  end
  
  def Relation.sql_sort_by_prestige
    " ORDER BY prestige DESC "
  end
  
end
